package client.inventory;

import database.BeePool;
import server.MapleItemInformationProvider;
import server.movement.LifeMovementFragment;
import server.movement.StaticLifeMovement;
import tools.FilePrinter;
import tools.FileoutputUtil;

import java.awt.*;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MaplePet implements Serializable {
    private static long serialVersionUID = 9179541993413738569L;
    private String name;
    private int uniqueid;
    private int petitemid;
    private int Fh;
    private int stance;
    private int limitedLife;
    private Point pos;
    private byte fullness;
    private byte level;
    private byte summoned;
    private short inventorypos;
    private short closeness;
    private short flags;
    private boolean changed;
    private int[] excluded;

    private MaplePet(int petitemid, int uniqueid) {
        this.Fh = 0;
        this.stance = 0;
        this.limitedLife = 0;
        this.fullness = 100;
        this.level = 1;
        this.summoned = 0;
        this.inventorypos = 0;
        this.closeness = 0;
        this.flags = 0;
        this.changed = false;
        this.excluded = new int[10];
        this.petitemid = petitemid;
        this.uniqueid = uniqueid;
        for (int i = 0; i < this.excluded.length; ++i) {
            this.excluded[i] = 0;
        }
    }

    private MaplePet(int petitemid, int uniqueid, short inventorypos) {
        this.Fh = 0;
        this.stance = 0;
        this.limitedLife = 0;
        this.fullness = 100;
        this.level = 1;
        this.summoned = 0;
        this.inventorypos = 0;
        this.closeness = 0;
        this.flags = 0;
        this.changed = false;
        this.excluded = new int[10];
        this.petitemid = petitemid;
        this.uniqueid = uniqueid;
        this.inventorypos = inventorypos;
        for (int i = 0; i < this.excluded.length; ++i) {
            this.excluded[i] = 0;
        }
    }

    public static MaplePet loadFromDb(int itemid, int petid, short inventorypos) {
        MaplePet ret = new MaplePet(itemid, petid, inventorypos);
        try (Connection con = BeePool.getConnection();
             PreparedStatement ps = con.prepareStatement("SELECT * FROM pets WHERE petid = ?")) {
            ps.setInt(1, petid);
            try (ResultSet rs = ps.executeQuery()) {
                if (!rs.next()) {
                    rs.close();
                    ps.close();
                    return null;
                }
                ret.setName(rs.getString("name"));
                ret.setCloseness((int) rs.getShort("closeness"));
                ret.setLevel((int) rs.getByte("level"));
                ret.setFullness((int) rs.getByte("fullness"));
                ret.setLimitedLife(rs.getInt("seconds"));
                ret.setFlags((int) rs.getShort("flags"));
                String[] list = rs.getString("excluded").split(",");
                for (int i = 0; i < ret.excluded.length; ++i) {
                    ret.excluded[i] = Integer.parseInt(list[i]);
                }
                ret.changed = false;
                rs.close();
            }
            ps.close();
            
            return ret;
        } catch (SQLException ex) {
            FilePrinter.printError("MaplePet.txt", (Throwable) ex, "loadFromDb");
            FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) ex);
            return null;
        }
    }

    public void saveToDb() {
        if (!this.changed) {
            return;
        }
        try (Connection con = BeePool.getConnection();
             PreparedStatement ps = con.prepareStatement("UPDATE pets SET name = ?, level = ?, closeness = ?, fullness = ?, seconds = ?, flags = ?, excluded = ?  WHERE petid = ?")) {
            ps.setString(1, this.name);
            ps.setByte(2, this.level);
            ps.setShort(3, this.closeness);
            ps.setByte(4, this.fullness);
            ps.setInt(5, this.limitedLife);
            ps.setShort(6, this.flags);
            StringBuilder list = new StringBuilder();
            for (int i = 0; i < this.excluded.length; ++i) {
                list.append(this.excluded[i]);
                list.append(",");
            }
            String newlist = list.toString();
            ps.setString(7, newlist.substring(0, newlist.length() - 1));
            ps.setInt(8, this.uniqueid);
            ps.executeUpdate();
            ps.close();
            
            this.changed = false;
        } catch (SQLException ex) {
            FilePrinter.printError("MaplePet.txt", (Throwable) ex, "saveToDb");
            FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) ex);
        }
    }

    public static MaplePet createPet(int itemid, int uniqueid) {
        MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
        return createPet(itemid, ii.getName(itemid), 1, 0, 100, uniqueid, ii.getPetLimitLife(itemid), ii.getPetFlagInfo(itemid));
    }

    public static MaplePet createPet(int itemid, String name, int level, int closeness, int fullness, int uniqueid, int limitedLife, short flag) {
        if (uniqueid <= -1) {
            uniqueid = MapleInventoryIdentifier.getInstance();
        }
        try (Connection con = BeePool.getConnection();
             PreparedStatement pse = con.prepareStatement("INSERT INTO pets (petid, name, level, closeness, fullness, seconds, flags) VALUES (?, ?, ?, ?, ?, ?, ?)")) {
            pse.setInt(1, uniqueid);
            pse.setString(2, name);
            pse.setByte(3, (byte) level);
            pse.setShort(4, (short) closeness);
            pse.setByte(5, (byte) fullness);
            pse.setInt(6, limitedLife);
            pse.setShort(7, flag);
            pse.executeUpdate();
            pse.close();
            
        } catch (SQLException ex) {
            FilePrinter.printError("MaplePet.txt", (Throwable) ex, "createPet");
            FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) ex);
            return null;
        }
        MaplePet pet = new MaplePet(itemid, uniqueid);
        pet.setName(name);
        pet.setLevel(level);
        pet.setFullness(fullness);
        pet.setCloseness(closeness);
        pet.setFlags((int) flag);
        pet.setLimitedLife(limitedLife);
        return pet;
    }

    public String getName() {
        if (this.name == null) {
            this.setName(MapleItemInformationProvider.getInstance().getName(this.petitemid));
        }
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
        this.changed = true;
    }

    public boolean getSummoned() {
        return this.summoned > 0;
    }

    public byte getSummonedValue() {
        return this.summoned;
    }

    public void setSummoned(int summoned) {
        this.summoned = (byte) summoned;
    }

    public short getInventoryPosition() {
        return this.inventorypos;
    }

    public void setInventoryPosition(short inventorypos) {
        this.inventorypos = inventorypos;
    }

    public int getUniqueId() {
        return this.uniqueid;
    }

    public short getCloseness() {
        return this.closeness;
    }

    public void setCloseness(int closeness) {
        if (closeness >= Integer.MAX_VALUE || closeness <= 0) {
            closeness = 1;
        }
        this.closeness = (short) closeness;
        this.changed = true;
    }

    public byte getLevel() {
        return this.level;
    }

    public void setLevel(int level) {
        this.level = (byte) level;
        this.changed = true;
    }

    public byte getFullness() {
        return this.fullness;
    }

    public void setFullness(int fullness) {
        this.fullness = (byte) fullness;
        this.changed = true;
    }

    public short getFlags() {
        return this.flags;
    }

    public void setFlags(int fffh) {
        this.flags = (short) fffh;
        this.changed = true;
    }

    public int getFh() {
        return this.Fh;
    }

    public void setFh(int Fh) {
        this.Fh = Fh;
    }

    public Point getPos() {
        return this.pos;
    }

    public void setPos(Point pos) {
        this.pos = pos;
    }

    public int getStance() {
        return this.stance;
    }

    public void setStance(int stance) {
        this.stance = stance;
    }

    public int getPetItemId() {
        return this.petitemid;
    }

    public boolean canConsume(int itemId) {
        MapleItemInformationProvider mii = MapleItemInformationProvider.getInstance();
        Iterator<Integer> iterator = mii.petsCanConsume(itemId).iterator();
        while (iterator.hasNext()) {
            int petId = ((Integer) iterator.next()).intValue();
            if (petId == this.petitemid) {
                return true;
            }
        }
        return false;
    }

    public void updatePosition(List<LifeMovementFragment> movement) {
        for (LifeMovementFragment move : movement) {
            if (move instanceof StaticLifeMovement) {
                Point newPos = move.getPosition();
                if (newPos == null) {
                    continue;
                }
                this.setPos(newPos);
                this.setStance(((StaticLifeMovement) move).getNewstate());
            }
        }
    }

    public int getSecondsLeft() {
        return this.limitedLife;
    }

    public void setLimitedLife(int sl) {
        this.limitedLife = sl;
        this.changed = true;
    }

    public static void main(String[] args) {
        clearPet();
    }

    public static void clearPet() {
        try (Connection con = BeePool.getConnection()) {
            PreparedStatement ps = con.prepareStatement("SELECT * FROM pets");
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                int uid = rs.getInt("petid");
                if (!ItemLoader.isExistsByUniqueid(uid)) {
                    ps = con.prepareStatement("DELETE FROM pets WHERE petid = ?");
                    ps.setInt(1, uid);
                    ps.executeUpdate();
                    System.err.println("宠物：" + rs.getString("name") + " petid: " + uid + " 不存在, 清理。");
                }
            }
            rs.close();
            ps.close();
            
        } catch (SQLException se) {
            System.err.println("[MaplePet] 从数据库中加载宠物讯息出错");
            FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) se);
        }
    }

    public void clearExcluded() {
        for (int i = 0; i < this.excluded.length; ++i) {
            this.excluded[i] = 0;
        }
        this.changed = true;
    }

    public List<Integer> getExcluded() {
        List list = new ArrayList();
        for (int i = 0; i < this.excluded.length; ++i) {
            if (this.excluded[i] > 0 && PetFlag.UNPICKABLE.check((int) this.flags)) {
                list.add(Integer.valueOf(this.excluded[i]));
            }
        }
        return (List<Integer>) list;
    }

    public void addExcluded(int i, int itemId) {
        if (i < this.excluded.length) {
            this.excluded[i] = itemId;
            this.changed = true;
        }
    }

    public enum PetFlag {
        ITEM_PICKUP(1, 5190000, 5191000),
        EXPAND_PICKUP(2, 5190002, 5191002),
        AUTO_PICKUP(4, 5190003, 5191003),
        UNPICKABLE(8, 5190005, -1),
        LEFTOVER_PICKUP(16, 5190004, 5191004),
        HP_CHARGE(32, 5190001, 5191001),
        MP_CHARGE(64, 5190006, -1),
        PET_BUFF(128, -1, -1),
        PET_DRAW(256, 5190007, -1),
        PET_DIALOGUE(512, 5190008, -1);

        private int i;
        private int item;
        private int remove;

        private PetFlag(int i, int item, int remove) {
            this.i = i;
            this.item = item;
            this.remove = remove;
        }

        public int getValue() {
            return this.i;
        }

        public boolean check(int flag) {
            return (flag & this.i) == this.i;
        }

        public static PetFlag getByAddId(int itemId) {
            for (PetFlag flag : values()) {
                if (flag.item == itemId) {
                    return flag;
                }
            }
            return null;
        }

        public static PetFlag getByDelId(int itemId) {
            for (PetFlag flag : values()) {
                if (flag.remove == itemId) {
                    return flag;
                }
            }
            return null;
        }
    }
}
